package org.dandsoft.blackbox.laboratory.tools.view;

import org.dandsoft.blackbox.laboratory.tools.JCRMonitorStorage;
import org.dandsoft.blackbox.snn.Signal;
import org.dandsoft.blackbox.snn.ObjectId;
import org.dandsoft.blackbox.snn.Time;

import javax.swing.table.*;
import javax.swing.*;
import java.awt.*;
import java.util.Map;
import java.util.Hashtable;
import java.util.Enumeration;

/**
 * Created by IntelliJ IDEA.
 * User: dvilyuzhanin
 * Date: 01.04.2009 18:44:36
 */
public class EnviromentStatePanel extends JPanel {

    private JCRMonitorStorage storage;
    private JTable table;
    private Integer timesCount;
    private Integer objectIdCount;
    private Map<Time, Map<ObjectId, Signal>> cache = new Hashtable<Time, Map<ObjectId, Signal>>();

    public EnviromentStatePanel() {
        setLayout(new BorderLayout());
        table = new JTable();
        table.setColumnModel(new ColumnModel());
        table.setModel(new StorageTableModel());
        table.setAutoscrolls(true);
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        table.setDefaultRenderer(Signal.class, new SignalRenderer());
        refresh();
        JScrollPane scrollPanel = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        add(scrollPanel, BorderLayout.CENTER);
    }


    class ColumnModel extends DefaultTableColumnModel {
        @Override
        public TableColumn getColumn(int columnIndex) {
            TableColumn column = super.getColumn(columnIndex);
            column.setWidth(2);
            column.setMinWidth(1);
            return column;
        }

        @Override
        public void addColumn(TableColumn aColumn) {
            aColumn.setWidth(2);
            aColumn.setMinWidth(1);
            super.addColumn(aColumn);
        }
    }
    class SignalRenderer extends JPanel implements TableCellRenderer {
        private Signal signal;

        SignalRenderer() {
            setPreferredSize(new Dimension(1, 1));
        }

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            if (value != null) {
                signal = (Signal) value;
                float floatValue = signal.getValue().getValue();
                int index = (int) Math.floor(floatValue * ValueColorSpec.SCALE_SIZE) - 1;
                setBackground(ValueColorSpec.getColor(index));
            } else {
                setBackground(Color.white);
            }
            return this;
        }

    }

    class StorageTableModel extends AbstractTableModel {

        public int getRowCount() {
            resizeColumn();
            if (timesCount == null && storage != null) {
                timesCount = (int) storage.getTimesCount();
            }
            if (timesCount != null) {
                return timesCount;
            } else {
                return 0;
            }
        }

        public int getColumnCount() {
            resizeColumn();
            if (objectIdCount == null && storage != null) {
                objectIdCount = storage.getMaxObjectId();
            }
            if (objectIdCount != null) {
                return objectIdCount;
            } else {
                return 0;
            }
        }

        public Object getValueAt(int timeRow, int idCloumn) {
            if (storage != null) {
                Time time = new Time(timeRow);
                ObjectId id = new ObjectId(idCloumn);
                Map<ObjectId, Signal> timeMap = cache.get(time);
                if (timeMap == null) {
                    timeMap = storage.getEnviroment(time);
                    if (timeMap == null) {
                        return null;
                    }
                    cache.put(time, timeMap);
                }
                Signal sigal = timeMap.get(id);
                return sigal;
            } else {
                return null;
            }
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return Signal.class;
        }
    }


    public JCRMonitorStorage getStorage() {
        return storage;
    }

    private void clear() {
        cache.clear();
        this.timesCount = null;
        this.objectIdCount = null;
    }

    private void refresh() {
        clear();
        table.setModel(new StorageTableModel());
        table.revalidate();
        table.repaint();
    }

    private void resizeColumn() {
        Enumeration<TableColumn> iter = table.getColumnModel().getColumns();
        while (iter.hasMoreElements()) {
            TableColumn column = iter.nextElement();
            column.setWidth(2);
        }
    }

    public void setStorage(JCRMonitorStorage storage) {
        this.storage = storage;
        refresh();
    }
}
